package zhh.tangbao.commodity.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import zhh.tangbao.commodity.constant.MachineRunningState;
import zhh.tangbao.commodity.manager.pickup.PickUpOrder;
import zhh.tangbao.websocket.WebSocketSendMessageService;
import zhh.tangbao.websocket.WebSocketServiceType;
import zhh.tangbao.websocket.pojo.MachineRunning;
import zhh.tangbao.websocket.pojo.WebSocketMessageEntity;

import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

/**
 * <p>
 *     取货队列管理
 *     维护外层一个Map结构，机器ID作为key，订单以及订单内容队列作为value
 *     每个机器中需要维护一个取货队列，可能会出现一个订单含于多个机器内
 * </p>
 * @author 粥灰灰
 * <p>2023/3/21</p>
 */

@Component
public class OrderPickUpManager {

    @Autowired
    private WebSocketSendMessageService sendMessageService;

    private Map<String, Integer> orderCountMap = Maps.newConcurrentMap();
    private Map<String, Queue<PickUpOrder>> pickQueueMap = Maps.newConcurrentMap();

    public void addPickUp(String machineId, PickUpOrder opu) {
        Queue<PickUpOrder> pickUpOrders = pickQueueMap.get(machineId);
        if (CollUtil.isEmpty(pickUpOrders)) {
            pickUpOrders = getQueue();
            pickQueueMap.put(machineId, pickUpOrders);
        }
        pickUpOrders.add(opu);
        Integer needPickUpCount = orderCountMap.get(opu.getOrderId());
        if (null != needPickUpCount) {
            orderCountMap.put(opu.getOrderId(), needPickUpCount + 1);
        }
        sendMessageService.sendMessageToAll(null, new WebSocketMessageEntity(WebSocketServiceType.MACHINE, new MachineRunning(machineId, MachineRunningState.RUNNING, pickUpOrders.size())));
    }

    public PickUpOrder pickUp(String machineId) {
        Queue<PickUpOrder> pickUpOrders = pickQueueMap.get(machineId);
        if (CollUtil.isEmpty(pickUpOrders)) {
            return null;
        }
        PickUpOrder poll = pickUpOrders.poll();
        Integer needPickUpCount = orderCountMap.get(poll.getOrderId());
        if (null != needPickUpCount) {
            orderCountMap.put(poll.getOrderId(), needPickUpCount - 1);
        }
        return poll;
    }

    public void addMachine(String machineId) {
        // 以防重新添加机器的时候导致取货队列被覆盖
        if (!pickQueueMap.containsKey(machineId)) {
            pickQueueMap.put(machineId, getQueue());
        }
    }

    public void removeMachine(String machineId) {
        pickQueueMap.remove(machineId);
    }


    /**
     * 获取第一个取货订单编号
     * @param machineId
     * @return
     */
    public PickUpOrder getHead(String machineId) {
        Queue<PickUpOrder> pickUpOrders = pickQueueMap.get(machineId);
        if (CollUtil.isEmpty(pickUpOrders)) {
            return null;
        }
        return pickUpOrders.peek();
    }

    /**
     * 前边还有多少人
     */
    public int waitCount(String machineId, String orderId) {
        Assert.notBlank(machineId, "机器ID不能为空");
        Assert.notBlank(orderId, "订单ID不能为空");
        int index = 0;
        Queue<PickUpOrder> pickUpOrders = pickQueueMap.get(machineId);
        if (CollUtil.isEmpty(pickUpOrders)) {
            return 0;
        }
        for (PickUpOrder pickUpOrder : pickUpOrders) {
            if (orderId.equals(pickUpOrder.getOrderId())) {
                break;
            }
            index++;
        }
        return index;
    }

    public int getQueueSize(String machineId) {
        Queue<PickUpOrder> pickUpOrders = pickQueueMap.get(machineId);
        if (CollUtil.isEmpty(pickUpOrders)) {
            return 0;
        }
        return pickUpOrders.size();
    }

    public boolean checkOrderCompleted(String orderId) {
        Integer integer = orderCountMap.get(orderId);
        if (null == integer || integer <= 0) {
            orderCountMap.remove(orderId);
            return true;
        }
        return false;
    }


    private Queue<PickUpOrder> getQueue() {
        return Lists.newLinkedList();
    }

}
